﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Encounters.PlayerEncounter
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Conversation;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.GameState;
using TaleWorlds.CampaignSystem.Inventory;
using TaleWorlds.CampaignSystem.Map;
using TaleWorlds.CampaignSystem.MapEvents;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Roster;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.CampaignSystem.Siege;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Encounters
{
  public class PlayerEncounter
  {
    [SaveableField(0)]
    public static bool EncounteredPartySurrendered;
    [SaveableField(1)]
    public bool FirstInit = true;
    public const float JoiningRadius = 3f;
    [SaveableField(5)]
    public bool IsEnemy;
    [SaveableField(7)]
    public float PlayerPartyInitialStrength;
    [SaveableField(8)]
    private CampaignBattleResult _campaignBattleResult;
    [SaveableField(9)]
    public float PartiesStrengthRatioBeforePlayerJoin;
    [SaveableField(10)]
    public bool ForceRaid;
    [SaveableField(11)]
    public bool ForceSallyOut;
    [SaveableField(32)]
    public bool ForceVolunteers;
    [SaveableField(33)]
    public bool ForceSupplies;
    [SaveableField(34)]
    private bool _isSiegeInterruptedByEnemyDefection;
    public BattleSimulation BattleSimulation;
    [SaveableField(13)]
    private MapEvent _mapEvent;
    [SaveableField(14)]
    private PlayerEncounterState _mapEventState;
    [SaveableField(15)]
    private PartyBase _encounteredParty;
    [SaveableField(16)]
    private PartyBase _attackerParty;
    [SaveableField(17)]
    private PartyBase _defenderParty;
    [SaveableField(18)]
    private List<Hero> _helpedHeroes;
    [SaveableField(19)]
    private List<TroopRosterElement> _capturedHeroes;
    [SaveableField(20)]
    private List<TroopRosterElement> _freedHeroes;
    [SaveableField(22)]
    private bool _leaveEncounter;
    [SaveableField(23)]
    private bool _playerSurrender;
    [SaveableField(24)]
    private bool _enemySurrender;
    [SaveableField(25)]
    private bool _battleChallenge;
    [SaveableField(26)]
    private bool _meetingDone;
    [SaveableField(27)]
    private bool _stateHandled;
    [SaveableField(36)]
    private ItemRoster _alternativeRosterToReceiveLootItems;
    [SaveableField(37)]
    private TroopRoster _alternativeRosterToReceiveLootPrisoners;
    [SaveableField(38)]
    private TroopRoster _alternativeRosterToReceiveLootMembers;
    [SaveableField(51)]
    private bool _doesBattleContinue;
    [SaveableField(52)]
    private bool _isSallyOutAmbush;

    internal static void AutoGeneratedStaticCollectObjectsPlayerEncounter(
      object o,
      List<object> collectedObjects)
    {
      ((PlayerEncounter) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._campaignBattleResult);
      collectedObjects.Add((object) this._mapEvent);
      collectedObjects.Add((object) this._encounteredParty);
      collectedObjects.Add((object) this._attackerParty);
      collectedObjects.Add((object) this._defenderParty);
      collectedObjects.Add((object) this._helpedHeroes);
      collectedObjects.Add((object) this._capturedHeroes);
      collectedObjects.Add((object) this._freedHeroes);
      collectedObjects.Add((object) this._alternativeRosterToReceiveLootItems);
      collectedObjects.Add((object) this._alternativeRosterToReceiveLootPrisoners);
      collectedObjects.Add((object) this._alternativeRosterToReceiveLootMembers);
      collectedObjects.Add((object) this.EncounterSettlementAux);
    }

    internal static object AutoGeneratedGetMemberValueOpponentSide(object o)
    {
      return (object) ((PlayerEncounter) o).OpponentSide;
    }

    internal static object AutoGeneratedGetMemberValuePlayerSide(object o)
    {
      return (object) ((PlayerEncounter) o).PlayerSide;
    }

    internal static object AutoGeneratedGetMemberValueIsJoinedBattle(object o)
    {
      return (object) ((PlayerEncounter) o).IsJoinedBattle;
    }

    internal static object AutoGeneratedGetMemberValueEncounterSettlementAux(object o)
    {
      return (object) ((PlayerEncounter) o).EncounterSettlementAux;
    }

    internal static object AutoGeneratedGetMemberValueIsPlayerWaiting(object o)
    {
      return (object) ((PlayerEncounter) o).IsPlayerWaiting;
    }

    internal static object AutoGeneratedGetMemberValueFirstInit(object o)
    {
      return (object) ((PlayerEncounter) o).FirstInit;
    }

    internal static object AutoGeneratedGetMemberValueIsEnemy(object o)
    {
      return (object) ((PlayerEncounter) o).IsEnemy;
    }

    internal static object AutoGeneratedGetMemberValuePlayerPartyInitialStrength(object o)
    {
      return (object) ((PlayerEncounter) o).PlayerPartyInitialStrength;
    }

    internal static object AutoGeneratedGetMemberValuePartiesStrengthRatioBeforePlayerJoin(object o)
    {
      return (object) ((PlayerEncounter) o).PartiesStrengthRatioBeforePlayerJoin;
    }

    internal static object AutoGeneratedGetMemberValueForceRaid(object o)
    {
      return (object) ((PlayerEncounter) o).ForceRaid;
    }

    internal static object AutoGeneratedGetMemberValueForceSallyOut(object o)
    {
      return (object) ((PlayerEncounter) o).ForceSallyOut;
    }

    internal static object AutoGeneratedGetMemberValueForceVolunteers(object o)
    {
      return (object) ((PlayerEncounter) o).ForceVolunteers;
    }

    internal static object AutoGeneratedGetMemberValueForceSupplies(object o)
    {
      return (object) ((PlayerEncounter) o).ForceSupplies;
    }

    internal static object AutoGeneratedGetMemberValue_campaignBattleResult(object o)
    {
      return (object) ((PlayerEncounter) o)._campaignBattleResult;
    }

    internal static object AutoGeneratedGetMemberValue_isSiegeInterruptedByEnemyDefection(object o)
    {
      return (object) ((PlayerEncounter) o)._isSiegeInterruptedByEnemyDefection;
    }

    internal static object AutoGeneratedGetMemberValue_mapEvent(object o)
    {
      return (object) ((PlayerEncounter) o)._mapEvent;
    }

    internal static object AutoGeneratedGetMemberValue_mapEventState(object o)
    {
      return (object) ((PlayerEncounter) o)._mapEventState;
    }

    internal static object AutoGeneratedGetMemberValue_encounteredParty(object o)
    {
      return (object) ((PlayerEncounter) o)._encounteredParty;
    }

    internal static object AutoGeneratedGetMemberValue_attackerParty(object o)
    {
      return (object) ((PlayerEncounter) o)._attackerParty;
    }

    internal static object AutoGeneratedGetMemberValue_defenderParty(object o)
    {
      return (object) ((PlayerEncounter) o)._defenderParty;
    }

    internal static object AutoGeneratedGetMemberValue_helpedHeroes(object o)
    {
      return (object) ((PlayerEncounter) o)._helpedHeroes;
    }

    internal static object AutoGeneratedGetMemberValue_capturedHeroes(object o)
    {
      return (object) ((PlayerEncounter) o)._capturedHeroes;
    }

    internal static object AutoGeneratedGetMemberValue_freedHeroes(object o)
    {
      return (object) ((PlayerEncounter) o)._freedHeroes;
    }

    internal static object AutoGeneratedGetMemberValue_leaveEncounter(object o)
    {
      return (object) ((PlayerEncounter) o)._leaveEncounter;
    }

    internal static object AutoGeneratedGetMemberValue_playerSurrender(object o)
    {
      return (object) ((PlayerEncounter) o)._playerSurrender;
    }

    internal static object AutoGeneratedGetMemberValue_enemySurrender(object o)
    {
      return (object) ((PlayerEncounter) o)._enemySurrender;
    }

    internal static object AutoGeneratedGetMemberValue_battleChallenge(object o)
    {
      return (object) ((PlayerEncounter) o)._battleChallenge;
    }

    internal static object AutoGeneratedGetMemberValue_meetingDone(object o)
    {
      return (object) ((PlayerEncounter) o)._meetingDone;
    }

    internal static object AutoGeneratedGetMemberValue_stateHandled(object o)
    {
      return (object) ((PlayerEncounter) o)._stateHandled;
    }

    internal static object AutoGeneratedGetMemberValue_alternativeRosterToReceiveLootItems(object o)
    {
      return (object) ((PlayerEncounter) o)._alternativeRosterToReceiveLootItems;
    }

    internal static object AutoGeneratedGetMemberValue_alternativeRosterToReceiveLootPrisoners(
      object o)
    {
      return (object) ((PlayerEncounter) o)._alternativeRosterToReceiveLootPrisoners;
    }

    internal static object AutoGeneratedGetMemberValue_alternativeRosterToReceiveLootMembers(
      object o)
    {
      return (object) ((PlayerEncounter) o)._alternativeRosterToReceiveLootMembers;
    }

    internal static object AutoGeneratedGetMemberValue_doesBattleContinue(object o)
    {
      return (object) ((PlayerEncounter) o)._doesBattleContinue;
    }

    internal static object AutoGeneratedGetMemberValue_isSallyOutAmbush(object o)
    {
      return (object) ((PlayerEncounter) o)._isSallyOutAmbush;
    }

    public static PlayerEncounter Current => Campaign.Current.PlayerEncounter;

    public static LocationEncounter LocationEncounter
    {
      get => Campaign.Current.LocationEncounter;
      set => Campaign.Current.LocationEncounter = value;
    }

    public static MapEvent Battle
    {
      get => PlayerEncounter.Current == null ? (MapEvent) null : PlayerEncounter.Current._mapEvent;
    }

    public static PartyBase EncounteredParty
    {
      get
      {
        return PlayerEncounter.Current != null ? PlayerEncounter.Current._encounteredParty : (PartyBase) null;
      }
    }

    public static MobileParty EncounteredMobileParty
    {
      get => PlayerEncounter.EncounteredParty?.MobileParty;
    }

    public static MapEvent EncounteredBattle
    {
      get
      {
        if (PlayerEncounter.Current._encounteredParty.MapEvent != null)
          return PlayerEncounter.Current._encounteredParty.MapEvent;
        return PlayerEncounter.Current._encounteredParty.IsSettlement && PlayerEncounter.Current._encounteredParty.SiegeEvent?.BesiegerCamp.LeaderParty.MapEvent != null ? PlayerEncounter.Current._encounteredParty.SiegeEvent.BesiegerCamp.LeaderParty.MapEvent : (MapEvent) null;
      }
    }

    public static BattleState BattleState => PlayerEncounter.Current._mapEvent.BattleState;

    public static BattleSideEnum WinningSide => PlayerEncounter.Current._mapEvent.WinningSide;

    public static bool BattleChallenge
    {
      get => PlayerEncounter.Current._battleChallenge;
      set => PlayerEncounter.Current._battleChallenge = value;
    }

    public static bool PlayerIsDefender
    {
      get => PlayerEncounter.Current.PlayerSide == BattleSideEnum.Defender;
    }

    public static bool PlayerIsAttacker
    {
      get => PlayerEncounter.Current.PlayerSide == BattleSideEnum.Attacker;
    }

    public static bool LeaveEncounter
    {
      get => PlayerEncounter.Current._leaveEncounter;
      set => PlayerEncounter.Current._leaveEncounter = value;
    }

    public static bool MeetingDone => PlayerEncounter.Current._meetingDone;

    public static bool PlayerSurrender
    {
      get => PlayerEncounter.Current._playerSurrender;
      set
      {
        if (!value)
          return;
        PlayerEncounter.Current.PlayerSurrenderInternal();
      }
    }

    public static bool EnemySurrender
    {
      get => PlayerEncounter.Current._enemySurrender;
      set
      {
        if (!value)
          return;
        PlayerEncounter.Current.EnemySurrenderInternal();
      }
    }

    public static bool IsActive => PlayerEncounter.Current != null;

    [SaveableProperty(2)]
    public BattleSideEnum OpponentSide { get; private set; }

    [SaveableProperty(3)]
    public BattleSideEnum PlayerSide { get; private set; }

    [SaveableProperty(6)]
    public bool IsJoinedBattle { get; private set; }

    public static bool InsideSettlement
    {
      get => MobileParty.MainParty.IsActive && MobileParty.MainParty.CurrentSettlement != null;
    }

    public static CampaignBattleResult CampaignBattleResult
    {
      get => PlayerEncounter.Current._campaignBattleResult;
      set => PlayerEncounter.Current._campaignBattleResult = value;
    }

    public static BattleSimulation CurrentBattleSimulation
    {
      get
      {
        return PlayerEncounter.Current == null ? (BattleSimulation) null : PlayerEncounter.Current.BattleSimulation;
      }
    }

    public PlayerEncounterState EncounterState
    {
      get => this._mapEventState;
      private set => this._mapEventState = value;
    }

    public ItemRoster RosterToReceiveLootItems
    {
      get
      {
        if (this._alternativeRosterToReceiveLootItems == null)
          this._alternativeRosterToReceiveLootItems = new ItemRoster();
        return this._alternativeRosterToReceiveLootItems;
      }
    }

    public TroopRoster RosterToReceiveLootPrisoners
    {
      get
      {
        if (this._alternativeRosterToReceiveLootPrisoners == (TroopRoster) null)
          this._alternativeRosterToReceiveLootPrisoners = TroopRoster.CreateDummyTroopRoster();
        return this._alternativeRosterToReceiveLootPrisoners;
      }
    }

    public TroopRoster RosterToReceiveLootMembers
    {
      get
      {
        if (this._alternativeRosterToReceiveLootMembers == (TroopRoster) null)
          this._alternativeRosterToReceiveLootMembers = TroopRoster.CreateDummyTroopRoster();
        return this._alternativeRosterToReceiveLootMembers;
      }
    }

    public static Settlement EncounterSettlement => PlayerEncounter.Current?.EncounterSettlementAux;

    [SaveableProperty(28)]
    public Settlement EncounterSettlementAux { get; private set; }

    [SaveableProperty(50)]
    public bool IsPlayerWaiting { get; set; }

    private PlayerEncounter()
    {
    }

    public void OnLoad()
    {
      if (PlayerEncounter.InsideSettlement && PlayerEncounter.Battle == null)
      {
        PlayerEncounter.CreateLocationEncounter(MobileParty.MainParty.CurrentSettlement);
      }
      else
      {
        if (PlayerEncounter.Current == null || PlayerEncounter.EncounterSettlement == null || !PlayerEncounter.EncounterSettlement.IsVillage || !PlayerEncounter.Current.IsPlayerWaiting)
          return;
        PlayerEncounter.CreateLocationEncounter(this.EncounterSettlementAux);
      }
    }

    public static void RestartPlayerEncounter(
      PartyBase defenderParty,
      PartyBase attackerParty,
      bool forcePlayerOutFromSettlement = true)
    {
      if (PlayerEncounter.Current != null)
        PlayerEncounter.Finish(forcePlayerOutFromSettlement);
      PlayerEncounter.Start();
      PlayerEncounter.Current.SetupFields(attackerParty, defenderParty);
    }

    internal static void SimulateBattle() => PlayerEncounter.Battle.SimulatePlayerEncounterBattle();

    internal void Init(PartyBase attackerParty, PartyBase defenderParty, Settlement settlement = null)
    {
      this.EncounterSettlementAux = settlement != null ? settlement : (defenderParty.IsSettlement ? defenderParty.Settlement : attackerParty.Settlement);
      PlayerEncounter.EncounteredPartySurrendered = false;
      this.PlayerPartyInitialStrength = PartyBase.MainParty.TotalStrength;
      this.SetupFields(attackerParty, defenderParty);
      if (defenderParty.MapEvent != null && attackerParty != MobileParty.MainParty.Party && defenderParty != MobileParty.MainParty.Party)
      {
        this._mapEvent = defenderParty.MapEvent;
        if (this._mapEvent.CanPartyJoinBattle(PartyBase.MainParty, BattleSideEnum.Defender))
          MobileParty.MainParty.Party.MapEventSide = this._mapEvent.DefenderSide;
        else if (this._mapEvent.CanPartyJoinBattle(PartyBase.MainParty, BattleSideEnum.Attacker))
          MobileParty.MainParty.Party.MapEventSide = this._mapEvent.AttackerSide;
      }
      bool joinBattle = false;
      bool startBattle = false;
      string encounterMenu = Campaign.Current.Models.EncounterGameMenuModel.GetEncounterMenu(attackerParty, defenderParty, out startBattle, out joinBattle);
      if (!string.IsNullOrEmpty(encounterMenu))
      {
        if (startBattle)
          PlayerEncounter.StartBattle();
        if (joinBattle)
        {
          if (MobileParty.MainParty.MapEvent == null)
          {
            if (defenderParty.MapEvent != null)
            {
              if (defenderParty.MapEvent.CanPartyJoinBattle(PartyBase.MainParty, BattleSideEnum.Attacker))
                PlayerEncounter.JoinBattle(BattleSideEnum.Attacker);
              else if (defenderParty.MapEvent.CanPartyJoinBattle(PartyBase.MainParty, BattleSideEnum.Defender))
                PlayerEncounter.JoinBattle(BattleSideEnum.Defender);
              else
                Debug.FailedAssert("false", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (Init), 461);
            }
            else
              Debug.FailedAssert("If there is no map event we should create one in order to join battle", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (Init), 466);
          }
          this.CheckNearbyPartiesToJoinPlayerMapEvent();
        }
        if (attackerParty == PartyBase.MainParty && defenderParty.IsSettlement && !defenderParty.Settlement.IsUnderRaid && !defenderParty.Settlement.IsUnderSiege)
          PlayerEncounter.EnterSettlement();
        GameMenu.ActivateGameMenu(encounterMenu);
      }
      else
      {
        if (attackerParty != PartyBase.MainParty || !defenderParty.IsSettlement || defenderParty.Settlement.IsUnderRaid || defenderParty.Settlement.IsUnderSiege)
          return;
        PlayerEncounter.EnterSettlement();
      }
    }

    public static void Init()
    {
      if (PlayerEncounter.Current == null)
        PlayerEncounter.Start();
      PlayerEncounter.Current.InitAux();
    }

    private void InitAux()
    {
      if (MobileParty.MainParty.MapEvent == null)
        return;
      this._mapEvent = MobileParty.MainParty.MapEvent;
      this.SetupFields(this._mapEvent.AttackerSide.LeaderParty, this._mapEvent.DefenderSide.LeaderParty);
      this.CheckNearbyPartiesToJoinPlayerMapEvent();
    }

    public void SetupFields(PartyBase attackerParty, PartyBase defenderParty)
    {
      this._attackerParty = attackerParty;
      this._defenderParty = defenderParty;
      MobileParty mobileParty = !defenderParty.IsMobile || defenderParty == PartyBase.MainParty || defenderParty.MobileParty == MobileParty.MainParty.AttachedTo ? (!attackerParty.IsMobile || attackerParty == PartyBase.MainParty || attackerParty.MobileParty == MobileParty.MainParty.AttachedTo ? (MobileParty) null : attackerParty.MobileParty) : defenderParty.MobileParty;
      if (this._defenderParty.IsSettlement)
        this.EncounterSettlementAux = defenderParty.Settlement;
      else if (this._attackerParty.IsSettlement)
        this.EncounterSettlementAux = this._attackerParty.Settlement;
      else if (mobileParty.BesiegerCamp != null)
        this.EncounterSettlementAux = mobileParty.BesiegerCamp.SiegeEvent.BesiegedSettlement;
      this._encounteredParty = mobileParty != null ? mobileParty.Party : this.EncounterSettlementAux?.Party;
      this.PlayerSide = MapEvent.PlayerMapEvent == null ? (defenderParty == PartyBase.MainParty || defenderParty.MobileParty != null && defenderParty.MobileParty == MobileParty.MainParty.AttachedTo || defenderParty.IsSettlement && (defenderParty.Settlement.MapFaction == MobileParty.MainParty.MapFaction || MobileParty.MainParty.CurrentSettlement == defenderParty.Settlement) ? BattleSideEnum.Defender : BattleSideEnum.Attacker) : MapEvent.PlayerMapEvent.PlayerSide;
      this.OpponentSide = this.PlayerSide.GetOppositeSide();
      if (this._encounteredParty.IsSettlement)
        return;
      MobileParty.MainParty.Ai.SetMoveModeHold();
    }

    internal void OnPartyJoinEncounter(MobileParty newParty)
    {
      if (PlayerEncounter.Battle == null)
        return;
      if (PlayerEncounter.Battle.CanPartyJoinBattle(PartyBase.MainParty, PartyBase.MainParty.Side))
      {
        newParty.Party.MapEventSide = PartyBase.MainParty.MapEventSide;
      }
      else
      {
        if (newParty == MobileParty.MainParty && PlayerEncounter.Battle.IsRaid && PlayerEncounter.Battle.AttackerSide.LeaderParty != MobileParty.MainParty.Party && PlayerEncounter.Battle.DefenderSide.TroopCount == 0)
          return;
        MobileParty.MainParty.Ai.SetMoveModeHold();
        string newPartyJoinMenu = Campaign.Current.Models.EncounterGameMenuModel.GetNewPartyJoinMenu(newParty);
        if (PlayerEncounter.Battle.CanPartyJoinBattle(PartyBase.MainParty, PartyBase.MainParty.OpponentSide))
          newParty.Party.MapEventSide = PartyBase.MainParty.MapEventSide.OtherSide;
        if (string.IsNullOrEmpty(newPartyJoinMenu))
          return;
        GameMenu.SwitchToMenu(newPartyJoinMenu);
      }
    }

    private void CheckNearbyPartiesToJoinPlayerMapEvent()
    {
      if (this._mapEvent == null || this._mapEvent.IsRaid || this._mapEvent.IsSiegeAssault || this._mapEvent.IsForcingSupplies || this._mapEvent.IsForcingVolunteers || this._mapEvent.MapEventSettlement != null && this._mapEvent.MapEventSettlement.IsHideout)
        return;
      List<MobileParty> partiesToJoinPlayerSide = new List<MobileParty>();
      List<MobileParty> partiesToJoinEnemySide = new List<MobileParty>();
      foreach (MapEventParty mapEventParty in (List<MapEventParty>) this._mapEvent.PartiesOnSide(this.PlayerSide))
      {
        if (mapEventParty.Party.IsMobile)
          partiesToJoinPlayerSide.Add(mapEventParty.Party.MobileParty);
      }
      foreach (MapEventParty mapEventParty in (List<MapEventParty>) this._mapEvent.PartiesOnSide(this.PlayerSide.GetOppositeSide()))
      {
        if (mapEventParty.Party.IsMobile)
          partiesToJoinEnemySide.Add(mapEventParty.Party.MobileParty);
      }
      PlayerEncounter.Current.FindNonAttachedNpcPartiesWhoWillJoinEvent(ref partiesToJoinPlayerSide, ref partiesToJoinEnemySide);
      foreach (MobileParty party in partiesToJoinPlayerSide)
        this._mapEvent.GetMapEventSide(this.PlayerSide).AddNearbyPartyToPlayerMapEvent(party);
      foreach (MobileParty party in partiesToJoinEnemySide)
        this._mapEvent.GetMapEventSide(this.PlayerSide.GetOppositeSide()).AddNearbyPartyToPlayerMapEvent(party);
    }

    private static TerrainType GetTerrainByCount(
      List<TerrainType> terrainTypeSamples,
      TerrainType currentPositionTerrainType)
    {
      for (int index = 0; index < terrainTypeSamples.Count; ++index)
      {
        if (terrainTypeSamples[index] == TerrainType.Snow)
          terrainTypeSamples[index] = TerrainType.Plain;
      }
      if (currentPositionTerrainType == TerrainType.Plain || currentPositionTerrainType == TerrainType.Desert || currentPositionTerrainType == TerrainType.Swamp || currentPositionTerrainType == TerrainType.Steppe)
      {
        int num = (int) ((double) terrainTypeSamples.Count * 0.33000001311302185);
        for (int index = 0; index < num; ++index)
          terrainTypeSamples.Add(currentPositionTerrainType);
      }
      Dictionary<TerrainType, int> dictionary = new Dictionary<TerrainType, int>();
      foreach (TerrainType terrainTypeSample in terrainTypeSamples)
      {
        if (!dictionary.ContainsKey(terrainTypeSample))
          dictionary.Add(terrainTypeSample, 1);
        else
          dictionary[terrainTypeSample]++;
      }
      KeyValuePair<TerrainType, int> keyValuePair1 = new KeyValuePair<TerrainType, int>(TerrainType.Plain, 0);
      foreach (KeyValuePair<TerrainType, int> keyValuePair2 in dictionary)
      {
        if ((keyValuePair2.Key == TerrainType.Plain || keyValuePair2.Key == TerrainType.Desert || keyValuePair2.Key == TerrainType.Swamp || keyValuePair2.Key == TerrainType.Steppe) && keyValuePair2.Value > keyValuePair1.Value)
          keyValuePair1 = keyValuePair2;
      }
      return keyValuePair1.Key;
    }

    private static List<TerrainType> GetSceneProperties(
      List<TerrainType> terrainTypeSamples,
      int forestCount,
      out ForestDensity forestDensity)
    {
      forestDensity = ForestDensity.None;
      float num = (float) forestCount / (float) terrainTypeSamples.Count;
      if ((double) num > 0.10000000149011612 && (double) num < 0.5)
        forestDensity = ForestDensity.Low;
      else if ((double) num >= 0.5)
        forestDensity = ForestDensity.High;
      List<TerrainType> sceneProperties = new List<TerrainType>();
      foreach (TerrainType terrainTypeSample in terrainTypeSamples)
      {
        if (!sceneProperties.Contains(terrainTypeSample))
          sceneProperties.Add(terrainTypeSample);
      }
      return sceneProperties;
    }

    public static string GetBattleSceneForMapPatch(MapPatchData mapPatch)
    {
      MBList<SingleplayerBattleSceneData> mbList = GameSceneDataManager.Instance.SingleplayerBattleScenes.Where<SingleplayerBattleSceneData>((Func<SingleplayerBattleSceneData, bool>) (scene => scene.MapIndices.Contains(mapPatch.sceneIndex))).ToMBList<SingleplayerBattleSceneData>();
      string sceneId;
      if (mbList.IsEmpty<SingleplayerBattleSceneData>())
      {
        Debug.FailedAssert("Battle scene for map patch with scene index " + (object) mapPatch.sceneIndex + " does not exist. Picking a random scene", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (GetBattleSceneForMapPatch), 735);
        sceneId = GameSceneDataManager.Instance.SingleplayerBattleScenes.GetRandomElement<SingleplayerBattleSceneData>().SceneID;
      }
      else if (mbList.Count > 1)
      {
        Debug.FailedAssert("Multiple battle scenes for map patch with scene index " + (object) mapPatch.sceneIndex + " are defined. Picking a matching scene randomly", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (GetBattleSceneForMapPatch), 740);
        sceneId = mbList.GetRandomElement<SingleplayerBattleSceneData>().SceneID;
      }
      else
        sceneId = mbList[0].SceneID;
      return sceneId;
    }

    public static string GetConversationSceneForMapPosition(Vec2 position2D)
    {
      TerrainType currentPositionTerrainType;
      List<TerrainType> terrainTypesCount = Campaign.Current.MapSceneWrapper.GetEnvironmentTerrainTypesCount(position2D, out currentPositionTerrainType);
      int forestCount = 0;
      foreach (TerrainType terrainType in terrainTypesCount)
        forestCount += terrainType == TerrainType.Forest ? 1 : 0;
      TerrainType terrainByCount = PlayerEncounter.GetTerrainByCount(terrainTypesCount, currentPositionTerrainType);
      ForestDensity forestDensity;
      List<TerrainType> sceneProperties = PlayerEncounter.GetSceneProperties(terrainTypesCount, forestCount, out forestDensity);
      int num1 = 0;
      Dictionary<ConversationSceneData, int> dictionary = new Dictionary<ConversationSceneData, int>();
      foreach (ConversationSceneData conversationScene in (List<ConversationSceneData>) GameSceneDataManager.Instance.ConversationScenes)
      {
        if (conversationScene.Terrain == terrainByCount)
        {
          int num2 = 0;
          if ((forestDensity != ForestDensity.None || conversationScene.ForestDensity != ForestDensity.None ? (forestDensity == ForestDensity.None ? 0 : (conversationScene.ForestDensity != 0 ? 1 : 0)) : 1) != 0)
            ++num2;
          int num3 = 2 - MathF.Abs(forestDensity - conversationScene.ForestDensity);
          int num4 = num2 + num3;
          foreach (TerrainType terrainType in sceneProperties)
          {
            if (conversationScene.TerrainTypes.Contains(terrainType))
              num4 += 3;
          }
          dictionary.Add(conversationScene, num4);
          if (num4 > num1)
            num1 = num4;
        }
      }
      MBList<ConversationSceneData> e = new MBList<ConversationSceneData>();
      foreach (KeyValuePair<ConversationSceneData, int> keyValuePair in dictionary)
      {
        if (keyValuePair.Value == num1)
          e.Add(keyValuePair.Key);
      }
      return (e.Count > 0 ? e.GetRandomElement<ConversationSceneData>() : GameSceneDataManager.Instance.ConversationScenes.GetRandomElement<ConversationSceneData>()).SceneID;
    }

    private MapEvent StartBattleInternal()
    {
      if (this._mapEvent == null)
      {
        if (this.ForceRaid)
          this._mapEvent = RaidEventComponent.CreateRaidEvent(this._attackerParty, this._defenderParty).MapEvent;
        else if (this.ForceSallyOut)
          this._mapEvent = Campaign.Current.MapEventManager.StartSallyOutMapEvent(this._attackerParty, this._defenderParty);
        else if (this.ForceVolunteers)
          this._mapEvent = ForceVolunteersEventComponent.CreateForceSuppliesEvent(this._attackerParty, this._defenderParty).MapEvent;
        else if (this.ForceSupplies)
          this._mapEvent = ForceSuppliesEventComponent.CreateForceSuppliesEvent(this._attackerParty, this._defenderParty).MapEvent;
        else if (this._defenderParty.IsSettlement)
        {
          if (this._defenderParty.Settlement.IsFortification)
            this._mapEvent = Campaign.Current.MapEventManager.StartSiegeMapEvent(this._attackerParty, this._defenderParty);
          else if (this._defenderParty.Settlement.IsVillage)
            this._mapEvent = RaidEventComponent.CreateRaidEvent(this._attackerParty, this._defenderParty).MapEvent;
          else if (this._defenderParty.Settlement.IsHideout)
            this._mapEvent = HideoutEventComponent.CreateHideoutEvent(this._attackerParty, this._defenderParty).MapEvent;
          else
            Debug.FailedAssert("Proper mapEvent type could not be set for the battle.", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (StartBattleInternal), 860);
        }
        else
          this._mapEvent = !this._isSallyOutAmbush ? (!this._attackerParty.IsMobile || this._attackerParty.MobileParty.CurrentSettlement == null || this._attackerParty.MobileParty.CurrentSettlement.SiegeEvent == null ? (!this._defenderParty.IsMobile || this._defenderParty.MobileParty.BesiegedSettlement == null ? FieldBattleEventComponent.CreateFieldBattleEvent(this._attackerParty, this._defenderParty).MapEvent : Campaign.Current.MapEventManager.StartSiegeOutsideMapEvent(this._attackerParty, this._defenderParty)) : Campaign.Current.MapEventManager.StartSallyOutMapEvent(this._attackerParty, this._defenderParty)) : SiegeAmbushEventComponent.CreateSiegeAmbushEvent(this._attackerParty, this._defenderParty).MapEvent;
      }
      this.CheckNearbyPartiesToJoinPlayerMapEvent();
      return this._mapEvent;
    }

    public static MapEvent StartBattle() => PlayerEncounter.Current.StartBattleInternal();

    private void JoinBattleInternal(BattleSideEnum side)
    {
      this.PlayerSide = side;
      switch (side)
      {
        case BattleSideEnum.Defender:
          this.OpponentSide = BattleSideEnum.Attacker;
          break;
        case BattleSideEnum.Attacker:
          this.OpponentSide = BattleSideEnum.Defender;
          break;
      }
      if (PlayerEncounter.EncounteredBattle != null)
      {
        this._mapEvent = PlayerEncounter.EncounteredBattle;
        this._encounteredParty = this.PlayerSide == BattleSideEnum.Attacker ? PlayerEncounter.EncounteredBattle.DefenderSide.LeaderParty : PlayerEncounter.EncounteredBattle.AttackerSide.LeaderParty;
        this.PartiesStrengthRatioBeforePlayerJoin = this.CalculateStrengthOfParties();
        PartyBase.MainParty.MapEventSide = PlayerEncounter.EncounteredBattle.GetMapEventSide(side);
        this.EncounterSettlementAux = this._mapEvent.MapEventSettlement;
        if (PlayerEncounter.EncounteredBattle.IsSiegeAssault && this.PlayerSide == BattleSideEnum.Attacker)
          MobileParty.MainParty.BesiegerCamp = this._encounteredParty.SiegeEvent.BesiegerCamp;
        this.IsJoinedBattle = true;
        this.CheckNearbyPartiesToJoinPlayerMapEvent();
      }
      else
        PlayerEncounter.Finish(PlayerEncounter.InsideSettlement);
    }

    private float CalculateStrengthOfParties()
    {
      float num1 = 0.0f;
      float num2 = 0.0f;
      foreach (MapEventParty party in (List<MapEventParty>) this._mapEvent.DefenderSide.Parties)
        num1 += party.Party.TotalStrength;
      foreach (MapEventParty party in (List<MapEventParty>) this._mapEvent.AttackerSide.Parties)
        num2 += party.Party.TotalStrength;
      return num1 / num2;
    }

    public static void JoinBattle(BattleSideEnum side)
    {
      PlayerEncounter.Current.JoinBattleInternal(side);
    }

    private void PlayerSurrenderInternal()
    {
      this._playerSurrender = true;
      if (PlayerEncounter.Battle == null)
        PlayerEncounter.StartBattle();
      this._mapEvent.DoSurrender(PartyBase.MainParty.Side);
      MobileParty.MainParty.BesiegerCamp = (BesiegerCamp) null;
    }

    private void EnemySurrenderInternal()
    {
      this._enemySurrender = true;
      this._mapEvent.DoSurrender(PartyBase.MainParty.OpponentSide);
    }

    public static void Start() => Campaign.Current.PlayerEncounter = new PlayerEncounter();

    public static void ProtectPlayerSide(float hoursToProtect = 1f)
    {
      MobileParty.MainParty.TeleportPartyToSafePosition();
      MobileParty.MainParty.IgnoreForHours(hoursToProtect);
    }

    public static void Finish(bool forcePlayerOutFromSettlement = true)
    {
      if (MobileParty.MainParty.Army == null || MobileParty.MainParty.Army.LeaderParty == PlayerEncounter.EncounteredMobileParty)
        Campaign.Current.TimeControlMode = CampaignTimeControlMode.Stop;
      if (Campaign.Current.CurrentMenuContext != null)
        GameMenu.ExitToLast();
      if (PlayerEncounter.Current != null)
      {
        int num = PlayerSiege.PlayerSiegeEvent == null || PlayerSiege.PlayerSide != BattleSideEnum.Attacker || MobileParty.MainParty.MapEvent == null || MobileParty.MainParty.MapEvent.IsSiegeAssault || !MobileParty.MainParty.MapEvent.HasWinner || MobileParty.MainParty.MapEvent.PlayerSide != BattleSideEnum.Defender ? 0 : (MobileParty.MainParty.BesiegedSettlement != null ? 1 : 0);
        if ((num != 0 || PlayerEncounter.Current._isSiegeInterruptedByEnemyDefection) && Hero.MainHero.PartyBelongedToAsPrisoner == null && !PlayerEncounter.Current._leaveEncounter && PlayerEncounter.Current._encounteredParty.MapFaction.IsAtWarWith(Hero.MainHero.MapFaction))
        {
          GameMenu.ActivateGameMenu("continue_siege_after_attack");
          if (PlayerEncounter.Current._isSiegeInterruptedByEnemyDefection)
            PlayerEncounter.Current._isSiegeInterruptedByEnemyDefection = false;
        }
        if ((num != 0 || PlayerEncounter.Current._isSiegeInterruptedByEnemyDefection) && Hero.MainHero.PartyBelongedToAsPrisoner != null && PlayerEncounter.Current._leaveEncounter)
          MobileParty.MainParty.BesiegerCamp = (BesiegerCamp) null;
        PlayerEncounter.Current.FirstInit = true;
        PlayerEncounter.EncounterSettlement?.OnPlayerEncounterFinish();
        PlayerEncounter.Current.FinalizeBattle();
        PlayerEncounter.Current.FinishEncounterInternal();
        if (PlayerEncounter.CurrentBattleSimulation != null)
        {
          MapState mapState = Game.Current.GameStateManager.LastOrDefault<MapState>();
          if (mapState != null && mapState.IsSimulationActive)
            mapState.EndBattleSimulation();
          PlayerEncounter.Current.BattleSimulation = (BattleSimulation) null;
        }
        if (((!PlayerEncounter.InsideSettlement ? 0 : (MobileParty.MainParty.AttachedTo == null ? 1 : 0)) & (forcePlayerOutFromSettlement ? 1 : 0)) != 0)
          PlayerEncounter.LeaveSettlement();
      }
      Campaign.Current.PlayerEncounter = (PlayerEncounter) null;
      Campaign.Current.LocationEncounter = (LocationEncounter) null;
      MobileParty.MainParty.Ai.SetMoveModeHold();
    }

    private void FinishEncounterInternal()
    {
      if (this._encounteredParty == null || !this._encounteredParty.IsMobile || MobileParty.MainParty.AttachedTo != null || !FactionManager.IsAtWarAgainstFaction(this._encounteredParty.MapFaction, PartyBase.MainParty.MapFaction) || !this._encounteredParty.MobileParty.IsActive)
        return;
      MobileParty.MainParty.TeleportPartyToSafePosition(0.3f, 0.1f);
      this._encounteredParty.MobileParty.Ai.SetDoNotAttackMainParty(2);
    }

    private void UpdateInternal()
    {
      this._mapEvent = MapEvent.PlayerMapEvent;
      if (PlayerEncounter.EncounteredPartySurrendered && this.EncounterState == PlayerEncounterState.Begin)
        this.EncounterState = PlayerEncounterState.Wait;
      this._stateHandled = false;
      while (!this._stateHandled)
      {
        if (PlayerEncounter.Current._leaveEncounter)
        {
          PlayerEncounter.Finish();
          this._stateHandled = true;
        }
        if (!this._stateHandled)
        {
          switch (this.EncounterState)
          {
            case PlayerEncounterState.Begin:
              this.DoBegin();
              continue;
            case PlayerEncounterState.Wait:
              this.DoWait();
              continue;
            case PlayerEncounterState.PrepareResults:
              this.DoPrepareResults();
              continue;
            case PlayerEncounterState.ApplyResults:
              this.DoApplyResults();
              continue;
            case PlayerEncounterState.PlayerVictory:
              this.DoPlayerVictory();
              continue;
            case PlayerEncounterState.PlayerTotalDefeat:
              this.DoPlayerDefeat();
              continue;
            case PlayerEncounterState.CaptureHeroes:
              this.DoCaptureHeroes();
              continue;
            case PlayerEncounterState.FreeHeroes:
              this.DoFreeHeroes();
              continue;
            case PlayerEncounterState.LootParty:
              this.DoLootParty();
              continue;
            case PlayerEncounterState.LootInventory:
              this.DoLootInventory();
              continue;
            case PlayerEncounterState.End:
              this.DoEnd();
              continue;
            default:
              Debug.FailedAssert("[DEBUG]Invalid map event state: " + (object) this._mapEventState, "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (UpdateInternal), 1132);
              continue;
          }
        }
      }
    }

    private void EndBattleByCheatInternal(bool playerWon)
    {
      if (!playerWon)
        return;
      foreach (MapEventParty mapEventParty in (List<MapEventParty>) this._mapEvent.PartiesOnSide(this.OpponentSide))
      {
        for (int index = 0; index < mapEventParty.Party.MemberRoster.Count; ++index)
        {
          int elementNumber = mapEventParty.Party.MemberRoster.GetElementNumber(index);
          int elementWoundedNumber = mapEventParty.Party.MemberRoster.GetElementWoundedNumber(index);
          int maxValue = elementNumber - elementWoundedNumber;
          int num = elementWoundedNumber + MBRandom.RandomInt(maxValue);
          int number = num > 0 || elementNumber < 0 ? num : 1;
          mapEventParty.Party.MemberRoster.SetElementNumber(index, number);
          mapEventParty.Party.MemberRoster.SetElementWoundedNumber(index, number);
        }
      }
    }

    public static void EndBattleByCheat(bool playerWon)
    {
      PlayerEncounter.Current.EndBattleByCheatInternal(playerWon);
    }

    public static void Update() => PlayerEncounter.Current.UpdateInternal();

    private void DoBegin()
    {
      this.EncounterState = PlayerEncounterState.Wait;
      this._stateHandled = true;
    }

    public static void DoMeeting() => PlayerEncounter.Current.DoMeetingInternal();

    public static void SetMeetingDone() => PlayerEncounter.Current._meetingDone = true;

    private void DoMeetingInternal()
    {
      PartyBase party1 = this._encounteredParty;
      if (party1.IsSettlement)
      {
        foreach (MapEventParty party2 in (List<MapEventParty>) MobileParty.MainParty.MapEvent.DefenderSide.Parties)
        {
          if (!party2.Party.IsSettlement)
          {
            party1 = party2.Party;
            break;
          }
        }
      }
      this.EncounterState = PlayerEncounterState.Begin;
      this._stateHandled = true;
      if ((!PlayerEncounter.PlayerIsAttacker || !this._defenderParty.IsMobile || this._defenderParty.MobileParty.Army == null || this._defenderParty.MobileParty.Army.LeaderParty != this._defenderParty.MobileParty ? 0 : (this._defenderParty.SiegeEvent != null ? 1 : (this._defenderParty.MobileParty.MapFaction.IsAtWarWith(MobileParty.MainParty.MapFaction) ? 0 : (!this._defenderParty.MobileParty.Army.LeaderParty.AttachedParties.Contains(MobileParty.MainParty) ? 1 : 0)))) != 0)
      {
        GameMenu.SwitchToMenu("army_encounter");
      }
      else
      {
        Campaign.Current.CurrentConversationContext = ConversationContext.PartyEncounter;
        this._meetingDone = true;
        CampaignMapConversation.OpenConversation(new ConversationCharacterData(CharacterObject.PlayerCharacter, PartyBase.MainParty, true), new ConversationCharacterData(ConversationHelper.GetConversationCharacterPartyLeader(party1), party1, true));
      }
    }

    private void ContinueBattle()
    {
      Debug.Print("[PlayerEncounter.ContinueBattle Start]");
      MapEventSide mapEventSide = this._mapEvent.GetMapEventSide(this._mapEvent.PlayerSide);
      MapEventSide otherSide = mapEventSide.OtherSide;
      this._mapEvent.RecalculateStrengthOfSides();
      float num1 = this._mapEvent.StrengthOfSide[(int) mapEventSide.MissionSide];
      float num2 = this._mapEvent.StrengthOfSide[(int) otherSide.MissionSide];
      float num3 = num1 / (num1 + num2);
      Debug.Print("playerSideStrength: " + (object) num1);
      Debug.Print("otherSideStrength: " + (object) num2);
      Debug.Print("playerSideStrengthRatio: " + (object) num3);
      if ((double) num3 >= 0.949999988079071 && otherSide.GetTotalHealthyHeroCountOfSide() <= 0)
      {
        Debug.Print("Player side wins according to the strength ratio.");
        this._mapEvent?.SetOverrideWinner(this._mapEvent.PlayerSide);
        PlayerEncounter.EnemySurrender = true;
        this.EncounterState = PlayerEncounterState.PrepareResults;
      }
      else if ((double) num3 < 0.05000000074505806 && mapEventSide.GetTotalHealthyHeroCountOfSide() <= 0)
      {
        Debug.Print("Other side wins according to the strength ratio.");
        this._mapEvent?.SetOverrideWinner(otherSide.MissionSide);
        this.EncounterState = PlayerEncounterState.PrepareResults;
      }
      else
      {
        Debug.Print("Battle continues.");
        Debug.Print("Other side strength by party:");
        foreach (MapEventParty party in (List<MapEventParty>) otherSide.Parties)
          Debug.Print("party: " + party.Party.Id + ": " + (object) party.Party.Name + ", strength: " + (object) party.Party.TotalStrength + ", healthy count: " + (object) party.Party.MemberRoster.TotalHealthyCount + ", wounded count: " + (object) party.Party.MemberRoster.TotalWounded);
        this._mapEvent.AttackerSide.CommitXpGains();
        this._mapEvent.DefenderSide.CommitXpGains();
        this._mapEvent.ApplyRenownAndInfluenceChanges();
        this._mapEvent.SetOverrideWinner(BattleSideEnum.None);
        if (this._mapEvent.IsSiegeAssault && otherSide == this._mapEvent.AttackerSide)
        {
          CampaignBattleResult campaignBattleResult = this._campaignBattleResult;
          if ((campaignBattleResult != null ? (campaignBattleResult.EnemyRetreated ? 1 : 0) : 0) != 0)
          {
            List<MapEventParty> list = this._mapEvent.AttackerSide.Parties.ToList<MapEventParty>();
            this._mapEvent.FinishBattleAndKeepSiegeEvent();
            this._mapEvent = (MapEvent) null;
            foreach (MapEventParty mapEventParty in list)
            {
              mapEventParty.Party.SetVisualAsDirty();
              if (mapEventParty.Party.IsMobile)
              {
                mapEventParty.Party.MobileParty.Ai.SetMoveBesiegeSettlement(Settlement.CurrentSettlement);
                mapEventParty.Party.MobileParty.Ai.RecalculateShortTermAi();
              }
            }
            GameMenu.ActivateGameMenu("menu_siege_strategies");
          }
        }
        this._campaignBattleResult = (CampaignBattleResult) null;
        this._stateHandled = true;
      }
      Debug.Print("[PlayerEncounter.ContinueBattle End]");
    }

    private void DoWait()
    {
      MBTextManager.SetTextVariable("PARTY", MapEvent.PlayerMapEvent.GetLeaderParty(PartyBase.MainParty.OpponentSide).Name, false);
      if (!PlayerEncounter.EncounteredPartySurrendered)
        MBTextManager.SetTextVariable("ENCOUNTER_TEXT", GameTexts.FindText("str_you_have_encountered_PARTY"), true);
      else
        MBTextManager.SetTextVariable("ENCOUNTER_TEXT", GameTexts.FindText("str_you_have_encountered_PARTY_they_surrendered"), true);
      if (this.CheckIfBattleShouldContinueAfterBattleMission())
      {
        this.ContinueBattle();
      }
      else
      {
        if (this._mapEvent != null && this._mapEvent.IsSiegeAssault)
        {
          this._mapEvent.CheckIfOneSideHasLost();
          this._campaignBattleResult = CampaignBattleResult.GetResult(this._mapEvent.BattleState);
        }
        if (this._campaignBattleResult != null && this._campaignBattleResult.BattleResolved)
        {
          if (this._campaignBattleResult.PlayerVictory)
          {
            this._mapEvent?.SetOverrideWinner(PartyBase.MainParty.Side);
          }
          else
          {
            bool flag = true;
            if (this._mapEvent != null && this._mapEvent.IsHideoutBattle)
            {
              this._mapEvent.MapEventSettlement.Hideout.UpdateNextPossibleAttackTime();
              if (this._mapEvent.GetMapEventSide(this.PlayerSide).RecalculateMemberCountOfSide() > 0)
                flag = false;
            }
            if (flag)
              this._mapEvent?.SetOverrideWinner(PartyBase.MainParty.OpponentSide);
          }
          this.EncounterState = PlayerEncounterState.PrepareResults;
        }
        else if (this.BattleSimulation != null && (PlayerEncounter.BattleState == BattleState.AttackerVictory || PlayerEncounter.BattleState == BattleState.DefenderVictory))
        {
          if (this._mapEvent.WinningSide == this.PlayerSide)
            PlayerEncounter.EnemySurrender = true;
          else if (MobileParty.MainParty.MemberRoster.TotalManCount - MobileParty.MainParty.MemberRoster.TotalWounded == 0)
            PlayerEncounter.PlayerSurrender = true;
          this.EncounterState = PlayerEncounterState.PrepareResults;
        }
        else if (this.BattleSimulation != null && this.BattleSimulation.IsSimulationFinished && this._mapEvent?.MapEventSettlement != null && PlayerEncounter.BattleState == BattleState.None && this._mapEvent.IsSiegeAssault && PlayerSiege.PlayerSiegeEvent != null)
        {
          this._stateHandled = true;
          PlayerSiege.PlayerSiegeEvent.BreakSiegeEngine(PlayerSiege.PlayerSiegeEvent.GetSiegeEventSide(this._mapEvent.PlayerSide), DefaultSiegeEngineTypes.Preparations);
        }
        else if (this._mapEvent != null && (!this._mapEvent.IsRaid || PlayerEncounter.PlayerSurrender) && this._mapEvent.HasWinner)
        {
          this.EncounterState = PlayerEncounterState.PrepareResults;
        }
        else
        {
          this._stateHandled = true;
          if (this.IsJoinedBattle && Campaign.Current.CurrentMenuContext != null && Campaign.Current.CurrentMenuContext.GameMenu.StringId == "join_encounter")
            PlayerEncounter.LeaveBattle();
          if (this._mapEvent == null || !this._mapEvent.IsHideoutBattle)
            return;
          this._mapEvent.MapEventSettlement.Hideout.UpdateNextPossibleAttackTime();
        }
      }
    }

    public static bool CheckIfLeadingAvaliable()
    {
      bool flag1 = Hero.MainHero.PartyBelongedTo != null && !Hero.MainHero.IsWounded;
      bool flag2 = Hero.MainHero.PartyBelongedTo != null && Hero.MainHero.PartyBelongedTo.Army != null && Hero.MainHero.PartyBelongedTo.Army.ArmyOwner != Hero.MainHero;
      bool flag3 = false;
      foreach (MapEventParty mapEventParty in (List<MapEventParty>) MobileParty.MainParty.MapEvent.PartiesOnSide(MobileParty.MainParty.MapEvent.PlayerSide))
      {
        if (mapEventParty.Party != MobileParty.MainParty.Party && mapEventParty.Party.LeaderHero != null && (double) mapEventParty.Party.LeaderHero.Clan.Renown > (double) Clan.PlayerClan.Renown)
        {
          flag3 = true;
          break;
        }
      }
      return flag1 && flag2 | flag3;
    }

    public static Hero GetLeadingHero()
    {
      if ((Hero.MainHero.PartyBelongedTo == null ? 0 : (Hero.MainHero.PartyBelongedTo.Army != null ? 1 : 0)) != 0)
        return MobileParty.MainParty.Army.ArmyOwner;
      foreach (MapEventParty mapEventParty in (List<MapEventParty>) MobileParty.MainParty.MapEvent.PartiesOnSide(MobileParty.MainParty.MapEvent.PlayerSide))
      {
        if (mapEventParty.Party != MobileParty.MainParty.Party && mapEventParty.Party.LeaderHero != null && (double) mapEventParty.Party.LeaderHero.Clan.Renown > (double) Clan.PlayerClan.Renown)
          return mapEventParty.Party.LeaderHero;
      }
      return Hero.MainHero;
    }

    private void DoPrepareResults()
    {
      this._mapEvent.CalculateBattleResults();
      this.EncounterState = PlayerEncounterState.ApplyResults;
    }

    public static void SetPlayerVictorious()
    {
      PlayerEncounter.Current.SetPlayerVictoriousInternal();
    }

    public void SetIsSallyOutAmbush(bool value)
    {
      if (PlayerEncounter.Current._isSallyOutAmbush && !value)
        this._campaignBattleResult = (CampaignBattleResult) null;
      PlayerEncounter.Current._isSallyOutAmbush = value;
    }

    public void SetPlayerSiegeInterruptedByEnemyDefection()
    {
      PlayerEncounter.Current._isSiegeInterruptedByEnemyDefection = true;
    }

    private void SetPlayerVictoriousInternal()
    {
      if (this.PlayerSide != BattleSideEnum.Attacker && this.PlayerSide != BattleSideEnum.Defender)
        return;
      this._mapEvent.SetOverrideWinner(this.PlayerSide);
    }

    public static void SetPlayerSiegeContinueWithDefenderPullBack()
    {
      PlayerEncounter.Current._mapEvent.SetDefenderPulledBack();
    }

    private void DoApplyResults()
    {
      CampaignEventDispatcher.Instance.OnPlayerBattleEnd(this._mapEvent);
      this._mapEvent.ApplyBattleResults();
      if (this._mapEvent.WinningSide == PartyBase.MainParty.Side)
        this.EncounterState = PlayerEncounterState.PlayerVictory;
      else if (this._mapEvent.DefeatedSide == PartyBase.MainParty.Side)
        this.EncounterState = PlayerEncounterState.PlayerTotalDefeat;
      else
        this.EncounterState = PlayerEncounterState.End;
    }

    public static void StartAttackMission()
    {
      PlayerEncounter.Current._campaignBattleResult = new CampaignBattleResult();
    }

    private void DoPlayerVictory()
    {
      if (this._helpedHeroes != null)
      {
        if (this._helpedHeroes.Count > 0)
        {
          if (this._helpedHeroes[0].DeathMark == KillCharacterAction.KillCharacterActionDetail.None)
          {
            Campaign.Current.CurrentConversationContext = ConversationContext.PartyEncounter;
            CampaignMapConversation.OpenConversation(new ConversationCharacterData(CharacterObject.PlayerCharacter, PartyBase.MainParty), new ConversationCharacterData(this._helpedHeroes[0].CharacterObject, this._helpedHeroes[0].PartyBelongedTo.Party));
          }
          this._helpedHeroes.RemoveAt(0);
          this._stateHandled = true;
        }
        else
          this.EncounterState = PlayerEncounterState.CaptureHeroes;
      }
      else
      {
        this._helpedHeroes = new List<Hero>();
        foreach (PartyBase involvedParty in MapEvent.PlayerMapEvent.InvolvedParties)
        {
          if (involvedParty != PartyBase.MainParty && involvedParty.Side == PartyBase.MainParty.Side && involvedParty.Owner != null && involvedParty.Owner != Hero.MainHero && involvedParty.LeaderHero != null && (MapEvent.PlayerMapEvent.AttackerSide.LeaderParty == involvedParty || MapEvent.PlayerMapEvent.DefenderSide.LeaderParty == involvedParty) && involvedParty.MobileParty != null && (involvedParty.MobileParty.Army == null || involvedParty.MobileParty.Army != MobileParty.MainParty.Army) && Campaign.Current.Models.BattleRewardModel.GetPlayerGainedRelationAmount(MapEvent.PlayerMapEvent, involvedParty.LeaderHero) > 0)
            this._helpedHeroes.Add(involvedParty.LeaderHero);
        }
      }
    }

    private void DoPlayerDefeat()
    {
      bool playerSurrender = PlayerEncounter.PlayerSurrender;
      PlayerEncounter.Finish();
      if (MobileParty.MainParty.BesiegerCamp != null)
      {
        if (MobileParty.MainParty.BesiegerCamp != null)
          MobileParty.MainParty.BesiegerCamp = (BesiegerCamp) null;
        else
          PlayerSiege.ClosePlayerSiege();
      }
      if (Hero.MainHero.DeathMark != KillCharacterAction.KillCharacterActionDetail.DiedInBattle)
        GameMenu.ActivateGameMenu(playerSurrender ? "taken_prisoner" : "defeated_and_taken_prisoner");
      this._stateHandled = true;
    }

    private void DoCaptureHeroes()
    {
      TroopRoster receivingLootShare = this._mapEvent.GetPrisonerRosterReceivingLootShare(PartyBase.MainParty);
      if (this._capturedHeroes == null)
        this._capturedHeroes = receivingLootShare.RemoveIf((Predicate<TroopRosterElement>) (lordElement => lordElement.Character.IsHero)).ToList<TroopRosterElement>();
      if (this._capturedHeroes.Count > 0)
      {
        TroopRosterElement capturedHero = this._capturedHeroes[this._capturedHeroes.Count - 1];
        Campaign.Current.CurrentConversationContext = ConversationContext.CapturedLord;
        ConversationCharacterData playerCharacterData = new ConversationCharacterData(CharacterObject.PlayerCharacter, PartyBase.MainParty);
        ConversationCharacterData conversationPartnerData = new ConversationCharacterData(capturedHero.Character, noHorse: true, noWeapon: true, spawnAfterFight: true);
        if (PlayerEncounter.InsideSettlement && Settlement.CurrentSettlement.IsHideout)
          CampaignMission.OpenConversationMission(playerCharacterData, conversationPartnerData);
        else
          CampaignMapConversation.OpenConversation(playerCharacterData, conversationPartnerData);
        Campaign.Current.ConversationManager.ConversationEndOneShot += (Action) (() => this._capturedHeroes.RemoveRange(this._capturedHeroes.Count - 1, 1));
        this._stateHandled = true;
      }
      else
        this.EncounterState = PlayerEncounterState.FreeHeroes;
    }

    private void DoFreeHeroes()
    {
      TroopRoster receivingLootShare = this._mapEvent.GetMemberRosterReceivingLootShare(PartyBase.MainParty);
      if (this._freedHeroes == null)
        this._freedHeroes = receivingLootShare.RemoveIf((Predicate<TroopRosterElement>) (lordElement => lordElement.Character.IsHero)).ToList<TroopRosterElement>();
      if (this._freedHeroes.Count > 0)
      {
        TroopRosterElement freedHero = this._freedHeroes[this._freedHeroes.Count - 1];
        Campaign.Current.CurrentConversationContext = ConversationContext.FreedHero;
        CampaignMapConversation.OpenConversation(new ConversationCharacterData(CharacterObject.PlayerCharacter, PartyBase.MainParty), new ConversationCharacterData(freedHero.Character, noHorse: true, noWeapon: true));
        Campaign.Current.ConversationManager.ConversationEndOneShot += (Action) (() => this._freedHeroes.RemoveRange(this._freedHeroes.Count - 1, 1));
        this._stateHandled = true;
      }
      else
        this.EncounterState = PlayerEncounterState.LootParty;
    }

    private void DoLootInventory()
    {
      ItemRoster receivingLootShare = this._mapEvent.GetItemRosterReceivingLootShare(PartyBase.MainParty);
      if (receivingLootShare.Count > 0)
      {
        InventoryManager.OpenScreenAsLoot(new Dictionary<PartyBase, ItemRoster>()
        {
          {
            PartyBase.MainParty,
            receivingLootShare
          }
        });
        this._stateHandled = true;
      }
      this.EncounterState = PlayerEncounterState.End;
    }

    private void DoLootParty()
    {
      TroopRoster receivingLootShare1 = this._mapEvent.GetMemberRosterReceivingLootShare(PartyBase.MainParty);
      TroopRoster receivingLootShare2 = this._mapEvent.GetPrisonerRosterReceivingLootShare(PartyBase.MainParty);
      if (receivingLootShare1.Count > 0 || receivingLootShare2.Count > 0)
      {
        PartyScreenManager.OpenScreenAsLoot(receivingLootShare1, receivingLootShare2, TextObject.Empty, receivingLootShare1.TotalManCount + receivingLootShare2.TotalManCount);
        this._stateHandled = true;
      }
      this.EncounterState = PlayerEncounterState.LootInventory;
    }

    public static void SacrificeTroops(int num, out TroopRoster losses, out ItemRoster lostBaggage)
    {
      PlayerEncounter.Current.SacrificeTroopsImp(num, out losses, out lostBaggage);
    }

    private void SacrificeTroopsImp(int num, out TroopRoster losses, out ItemRoster lostBaggage)
    {
      losses = new TroopRoster((PartyBase) null);
      lostBaggage = new ItemRoster();
      this._mapEvent.GetMapEventSide(this.PlayerSide).MakeReadyForSimulation((FlattenedTroopRoster) null);
      this.RemoveRandomTroops(num, losses);
      this.RemoveRandomItems(lostBaggage);
    }

    private void RemoveRandomItems(ItemRoster lostBaggage)
    {
      foreach (ItemRosterElement itemRosterElement in new ItemRoster(PartyBase.MainParty.ItemRoster))
      {
        if (!itemRosterElement.EquipmentElement.Item.NotMerchandise)
        {
          int number = MBRandom.RoundRandomized((float) itemRosterElement.Amount * 0.15f);
          PartyBase.MainParty.ItemRoster.AddToCounts(itemRosterElement.EquipmentElement, -number);
          lostBaggage.AddToCounts(itemRosterElement.EquipmentElement, number);
        }
      }
    }

    public void RemoveRandomTroops(int num, TroopRoster sacrifiedTroops)
    {
      int ofRegularMembers = MobileParty.MainParty.Party.NumberOfRegularMembers;
      if (MobileParty.MainParty.Army != null)
      {
        foreach (MobileParty attachedParty in (List<MobileParty>) MobileParty.MainParty.Army.LeaderParty.AttachedParties)
          ofRegularMembers += attachedParty.Party.NumberOfRegularMembers;
      }
      float sacrifaceRatio = (float) num / (float) ofRegularMembers;
      this.SacrifaceTroopsWithRatio(MobileParty.MainParty, sacrifaceRatio, sacrifiedTroops);
      if (MobileParty.MainParty.Army == null)
        return;
      foreach (MobileParty attachedParty in (List<MobileParty>) MobileParty.MainParty.Army.LeaderParty.AttachedParties)
        this.SacrifaceTroopsWithRatio(attachedParty, sacrifaceRatio, sacrifiedTroops);
    }

    private void SacrifaceTroopsWithRatio(
      MobileParty mobileParty,
      float sacrifaceRatio,
      TroopRoster sacrifiedTroops)
    {
      int num1 = MBRandom.RoundRandomized((float) mobileParty.Party.NumberOfRegularMembers * sacrifaceRatio);
      for (int index = 0; index < num1; ++index)
      {
        float num2 = 100f;
        TroopRosterElement troopRosterElement1 = mobileParty.Party.MemberRoster.GetTroopRoster().FirstOrDefault<TroopRosterElement>();
        foreach (TroopRosterElement troopRosterElement2 in (List<TroopRosterElement>) mobileParty.Party.MemberRoster.GetTroopRoster())
        {
          float num3 = (float) ((double) troopRosterElement2.Character.Level - (troopRosterElement2.WoundedNumber > 0 ? 0.5 : 0.0) - (double) MBRandom.RandomFloat * 0.5);
          if (!troopRosterElement2.Character.IsHero && (double) num3 < (double) num2 && troopRosterElement2.Number > 0)
          {
            num2 = num3;
            troopRosterElement1 = troopRosterElement2;
          }
        }
        mobileParty.MemberRoster.AddToCounts(troopRosterElement1.Character, -1, woundedCount: troopRosterElement1.WoundedNumber > 0 ? -1 : 0);
        sacrifiedTroops.AddToCounts(troopRosterElement1.Character, 1);
      }
    }

    private void DoEnd()
    {
      MapEvent mapEvent = this._mapEvent;
      int num = mapEvent != null ? (mapEvent.IsSiegeAssault ? 1 : 0) : 0;
      bool isHideoutBattle = this._mapEvent.IsHideoutBattle;
      bool flag1 = num != 0 && MobileParty.MainParty.MapEvent != null && MobileParty.MainParty.MapEvent == this._mapEvent;
      bool flag2 = MobileParty.MainParty.MapEvent != null && this.PlayerSide == BattleSideEnum.Attacker;
      bool isRaid = this._mapEvent.IsRaid;
      bool forcingVolunteers = this._mapEvent.IsForcingVolunteers;
      bool isForcingSupplies = this._mapEvent.IsForcingSupplies;
      bool flag3 = this.BattleSimulation != null && this._mapEvent.WinningSide != this.PlayerSide;
      Settlement mapEventSettlement = this._mapEvent.MapEventSettlement;
      BattleState battleState = this._mapEvent.BattleState;
      this._stateHandled = true;
      if (!flag3)
        PlayerEncounter.Finish();
      else
        PlayerEncounter.Battle.ResetBattleResults();
      if (num != 0)
      {
        if (mapEventSettlement == null)
          return;
        if (flag1)
        {
          if (!flag2)
            return;
          EncounterManager.StartSettlementEncounter(MobileParty.MainParty.Army != null ? MobileParty.MainParty.Army.LeaderParty : MobileParty.MainParty, mapEventSettlement);
          GameMenu.SwitchToMenu("menu_settlement_taken");
        }
        else
        {
          if (!PlayerEncounter.InsideSettlement)
            return;
          PlayerEncounter.LeaveSettlement();
        }
      }
      else if (isRaid | forcingVolunteers | isForcingSupplies)
      {
        if (this._attackerParty.IsMobile && this._attackerParty.MobileParty.Army != null && this._attackerParty.MobileParty.Army.LeaderParty != this._attackerParty.MobileParty || !flag2 || this._attackerParty != MobileParty.MainParty.Party)
          return;
        EncounterManager.StartSettlementEncounter(MobileParty.MainParty, mapEventSettlement);
        PlayerEncounter.Current.ForceSupplies = isForcingSupplies;
        PlayerEncounter.Current.ForceVolunteers = forcingVolunteers;
        PlayerEncounter.Current.ForceRaid = isRaid;
        BeHostileAction.ApplyEncounterHostileAction(PartyBase.MainParty, Settlement.CurrentSettlement.Party);
        if (isForcingSupplies)
          GameMenu.SwitchToMenu("force_supplies_village");
        else if (forcingVolunteers)
        {
          GameMenu.SwitchToMenu("force_volunteers_village");
        }
        else
        {
          if (!isRaid)
            return;
          if (PlayerEncounter.InsideSettlement)
            LeaveSettlementAction.ApplyForParty(MobileParty.MainParty);
          PlayerEncounter.StartBattle();
          GameMenu.SwitchToMenu("raiding_village");
          PlayerEncounter.Current.ForceRaid = false;
          PlayerEncounter.Current.ForceVolunteers = false;
          PlayerEncounter.Current.ForceSupplies = false;
        }
      }
      else if (isHideoutBattle)
      {
        if (mapEventSettlement == null)
          return;
        switch (battleState)
        {
          case BattleState.None:
            EncounterManager.StartSettlementEncounter(MobileParty.MainParty, mapEventSettlement);
            GameMenu.SwitchToMenu("hideout_after_defeated_and_saved");
            break;
          case BattleState.AttackerVictory:
            if (mapEventSettlement.Parties.Count > 0)
            {
              foreach (MobileParty mobileParty in new List<MobileParty>((IEnumerable<MobileParty>) mapEventSettlement.Parties))
              {
                LeaveSettlementAction.ApplyForParty(mobileParty);
                mobileParty.Ai.SetDoNotAttackMainParty(3);
              }
            }
            mapEventSettlement.Hideout.IsSpotted = false;
            mapEventSettlement.IsVisible = false;
            break;
        }
      }
      else
      {
        if (!flag3)
          return;
        this.EncounterState = PlayerEncounterState.Begin;
        GameMenu.SwitchToMenu("encounter");
      }
    }

    public bool CheckIfBattleShouldContinueAfterBattleMission()
    {
      if (this._doesBattleContinue || this._campaignBattleResult != null)
        this._doesBattleContinue = this._mapEvent.CheckIfBattleShouldContinueAfterBattleMission(this._campaignBattleResult);
      return this._doesBattleContinue;
    }

    public void FinalizeBattle()
    {
      if (this._mapEvent == null)
        return;
      if (this._mapEvent.HasWinner || this._mapEvent.DiplomaticallyFinished || this._mapEvent.IsSiegeAmbush || this._mapEvent.IsRaid && this._mapEvent.MapEventSettlement.SettlementHitPoints.ApproximatelyEqualsTo(0.0f))
      {
        MobileParty mobileParty = this._mapEvent.AttackerSide.LeaderParty.MobileParty;
        bool flag = this._mapEvent.IsRaid && this._mapEvent.BattleState == BattleState.AttackerVictory && !this._mapEvent.MapEventSettlement.SettlementHitPoints.ApproximatelyEqualsTo(0.0f);
        Settlement mapEventSettlement = this._mapEvent.MapEventSettlement;
        this._mapEvent.FinalizeEvent();
        this._mapEvent = (MapEvent) null;
        if (!(mobileParty != MobileParty.MainParty & flag))
          return;
        mobileParty.Ai.SetMoveRaidSettlement(mapEventSettlement);
        mobileParty.Ai.RecalculateShortTermAi();
      }
      else
        PlayerEncounter.LeaveBattle();
    }

    public void FindNonAttachedNpcPartiesWhoWillJoinEvent(
      ref List<MobileParty> partiesToJoinPlayerSide,
      ref List<MobileParty> partiesToJoinEnemySide)
    {
      MapEvent mapEvent = this._mapEvent;
      LocatableSearchData<MobileParty> data = MobileParty.StartFindingLocatablesAroundPosition(mapEvent != null ? mapEvent.Position : MobileParty.MainParty.Position2D, 4f);
      MobileParty nextLocatable = MobileParty.FindNextLocatable(ref data);
      List<MobileParty> mobilePartyList1 = new List<MobileParty>();
      List<MobileParty> mobilePartyList2 = new List<MobileParty>();
      for (; nextLocatable != null; nextLocatable = MobileParty.FindNextLocatable(ref data))
      {
        if (nextLocatable != MobileParty.MainParty && nextLocatable.MapEvent == null && nextLocatable.SiegeEvent == null && nextLocatable.CurrentSettlement == null && nextLocatable.AttachedTo == null && (nextLocatable.IsLordParty || nextLocatable.IsBandit || nextLocatable.ShouldJoinPlayerBattles))
        {
          if (!nextLocatable.MapFaction.IsAtWarWith(MobileParty.MainParty.MapFaction) && nextLocatable.MapFaction.IsAtWarWith(PlayerEncounter.EncounteredParty.MapFaction))
            mobilePartyList1.Add(nextLocatable);
          if (nextLocatable.MapFaction.IsAtWarWith(MobileParty.MainParty.MapFaction) && !nextLocatable.MapFaction.IsAtWarWith(PlayerEncounter.EncounteredParty.MapFaction))
            mobilePartyList2.Add(nextLocatable);
        }
      }
      if (mobilePartyList2.AnyQ<MobileParty>((Func<MobileParty, bool>) (t => t.ShouldBeIgnored)) || partiesToJoinEnemySide.AnyQ<MobileParty>((Func<MobileParty, bool>) (t => t.ShouldBeIgnored)))
      {
        Debug.Print("Ally parties wont join player encounter since there is an ignored party in enemy side");
        mobilePartyList1.Clear();
      }
      if (mobilePartyList1.AnyQ<MobileParty>((Func<MobileParty, bool>) (t => t.ShouldBeIgnored)) || partiesToJoinPlayerSide.AnyQ<MobileParty>((Func<MobileParty, bool>) (t => t != MobileParty.MainParty && t.ShouldBeIgnored)))
      {
        Debug.Print("Enemy parties wont join player encounter since there is an ignored party in ally side");
        mobilePartyList2.Clear();
      }
      partiesToJoinPlayerSide.AddRange(mobilePartyList1.Except<MobileParty>((IEnumerable<MobileParty>) partiesToJoinPlayerSide));
      partiesToJoinEnemySide.AddRange(mobilePartyList2.Except<MobileParty>((IEnumerable<MobileParty>) partiesToJoinEnemySide));
    }

    public void FindAllNpcPartiesWhoWillJoinEvent(
      ref List<MobileParty> partiesToJoinPlayerSide,
      ref List<MobileParty> partiesToJoinEnemySide)
    {
      this.FindNonAttachedNpcPartiesWhoWillJoinEvent(ref partiesToJoinPlayerSide, ref partiesToJoinEnemySide);
      foreach (MobileParty mobileParty in partiesToJoinPlayerSide.ToList<MobileParty>())
        partiesToJoinPlayerSide.AddRange(mobileParty.AttachedParties.Except<MobileParty>((IEnumerable<MobileParty>) partiesToJoinPlayerSide));
      foreach (MobileParty mobileParty in partiesToJoinEnemySide.ToList<MobileParty>())
        partiesToJoinEnemySide.AddRange(mobileParty.AttachedParties.Except<MobileParty>((IEnumerable<MobileParty>) partiesToJoinEnemySide));
    }

    public static void EnterSettlement()
    {
      Settlement encounterSettlement = PlayerEncounter.EncounterSettlement;
      PlayerEncounter.CreateLocationEncounter(encounterSettlement);
      EnterSettlementAction.ApplyForParty(MobileParty.MainParty, encounterSettlement);
    }

    private static void CreateLocationEncounter(Settlement settlement)
    {
      if (settlement.IsTown)
        PlayerEncounter.LocationEncounter = (LocationEncounter) new TownEncounter(settlement);
      else if (settlement.IsVillage)
      {
        PlayerEncounter.LocationEncounter = (LocationEncounter) new VillageEncounter(settlement);
      }
      else
      {
        if (!settlement.IsCastle)
          return;
        PlayerEncounter.LocationEncounter = (LocationEncounter) new CastleEncounter(settlement);
      }
    }

    public static void LeaveBattle()
    {
      MapEvent playerMapEvent = MapEvent.PlayerMapEvent;
      bool flag = false;
      if (playerMapEvent != null)
      {
        int numberOfInvolvedMen = playerMapEvent.GetNumberOfInvolvedMen(PartyBase.MainParty.Side);
        Army playerArmy = MobileParty.MainParty.Army;
        if (PartyBase.MainParty.MapEventSide.LeaderParty != PartyBase.MainParty && PartyBase.MainParty.MapEventSide.Parties.Any<MapEventParty>((Func<MapEventParty, bool>) (p =>
        {
          if (!p.IsNpcParty)
            return false;
          return playerArmy == null || p.Party.MobileParty?.Army != playerArmy;
        })) || PartyBase.MainParty.MapEvent.IsSallyOut && Campaign.Current.Models.EncounterModel.GetLeaderOfMapEvent(PartyBase.MainParty.MapEvent, PartyBase.MainParty.MapEventSide.MissionSide) != Hero.MainHero)
          PartyBase.MainParty.MapEventSide = (MapEventSide) null;
        else
          playerMapEvent.FinalizeEvent();
        int ofHealthyMembers = PartyBase.MainParty.NumberOfHealthyMembers;
        flag = numberOfInvolvedMen > ofHealthyMembers && playerMapEvent.AttackerSide.LeaderParty != PartyBase.MainParty && playerMapEvent.DefenderSide.LeaderParty != PartyBase.MainParty;
      }
      if (PlayerEncounter.CurrentBattleSimulation != null)
      {
        MapState mapState = Game.Current.GameStateManager.LastOrDefault<MapState>();
        if (mapState != null && mapState.IsSimulationActive)
          mapState.EndBattleSimulation();
        PlayerEncounter.Current.BattleSimulation = (BattleSimulation) null;
        PlayerEncounter.Current._mapEvent.BattleObserver = (IBattleObserver) null;
      }
      PlayerEncounter.Current.IsJoinedBattle = false;
      PlayerEncounter.Current._mapEvent = (MapEvent) null;
      if (!flag || playerMapEvent.HasWinner)
        return;
      playerMapEvent.SimulateBattleSetup(PlayerEncounter.Current.BattleSimulation?.SelectedTroops);
    }

    public static void LeaveSettlement()
    {
      LeaveSettlementAction.ApplyForParty(MobileParty.MainParty);
      PlayerEncounter.LocationEncounter = (LocationEncounter) null;
      PartyBase.MainParty.SetVisualAsDirty();
    }

    public static void InitSimulation(
      FlattenedTroopRoster selectedTroopsForPlayerSide,
      FlattenedTroopRoster selectedTroopsForOtherSide)
    {
      if (PlayerEncounter.Current == null)
        return;
      PlayerEncounter.Current.BattleSimulation = new BattleSimulation(selectedTroopsForPlayerSide, selectedTroopsForOtherSide);
    }

    public void InterruptEncounter(string encounterInterrupedType)
    {
      TaleWorlds.Core.GameState activeState = Game.Current.GameStateManager.ActiveState;
      if (MapEvent.PlayerMapEvent != null)
        PlayerEncounter.LeaveBattle();
      GameMenu.ActivateGameMenu(encounterInterrupedType);
    }

    public static void StartSiegeAmbushMission()
    {
      Settlement mapEventSettlement = PlayerEncounter.Battle.MapEventSettlement;
      SiegeEvent playerSiegeEvent = PlayerSiege.PlayerSiegeEvent;
      switch (mapEventSettlement.CurrentSiegeState)
      {
        case Settlement.SiegeState.OnTheWalls:
          List<MissionSiegeWeapon> activeSiegeEngines1 = playerSiegeEvent.GetPreparedAndActiveSiegeEngines(playerSiegeEvent.GetSiegeEventSide(BattleSideEnum.Attacker));
          List<MissionSiegeWeapon> activeSiegeEngines2 = playerSiegeEvent.GetPreparedAndActiveSiegeEngines(playerSiegeEvent.GetSiegeEventSide(BattleSideEnum.Defender));
          bool hasAnySiegeTower = activeSiegeEngines1.Exists((Predicate<MissionSiegeWeapon>) (data => data.Type == DefaultSiegeEngineTypes.SiegeTower));
          int wallLevel = mapEventSettlement.Town.GetWallLevel();
          CampaignMission.OpenSiegeMissionWithDeployment(mapEventSettlement.LocationComplex.GetLocationWithId("center").GetSceneName(wallLevel), mapEventSettlement.SettlementWallSectionHitPointsRatioList.ToArray(), hasAnySiegeTower, activeSiegeEngines1, activeSiegeEngines2, PlayerEncounter.Current.PlayerSide == BattleSideEnum.Attacker, wallLevel, true);
          break;
        case Settlement.SiegeState.InTheLordsHall:
        case Settlement.SiegeState.Invalid:
          Debug.FailedAssert("Siege state is invalid!", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (StartSiegeAmbushMission), 2226);
          break;
      }
    }

    public static void StartVillageBattleMission()
    {
      Settlement mapEventSettlement = PlayerEncounter.Battle.MapEventSettlement;
      int upgradeLevel = mapEventSettlement.IsTown ? mapEventSettlement.Town.GetWallLevel() : 1;
      CampaignMission.OpenBattleMission(mapEventSettlement.LocationComplex.GetScene("village_center", upgradeLevel), true);
    }

    public static void StartCombatMissionWithDialogueInTownCenter(CharacterObject characterToTalkTo)
    {
      int wallLevel = Settlement.CurrentSettlement.Town.GetWallLevel();
      CampaignMission.OpenCombatMissionWithDialogue(Settlement.CurrentSettlement.LocationComplex.GetScene("center", wallLevel), characterToTalkTo, wallLevel);
    }

    public static void StartHostileAction() => PlayerEncounter.Current.StartHostileActionInternal();

    private void StartHostileActionInternal()
    {
      if (this._mapEvent == null)
        return;
      if (PlayerEncounter.InsideSettlement)
        PlayerEncounter.LeaveSettlement();
      PlayerEncounter.Update();
    }

    public void FinishRaid()
    {
      Settlement mapEventSettlement = PlayerEncounter.Battle.MapEventSettlement;
      int num = PlayerEncounter.Battle.DiplomaticallyFinished ? 1 : 0;
      PartyBase leaderParty = PlayerEncounter.Battle.AttackerSide.LeaderParty;
      PlayerEncounter.Finish();
      if (num != 0)
        return;
      if (leaderParty == MobileParty.MainParty.Party)
        GameMenu.ActivateGameMenu("village_player_raid_ended");
      else
        GameMenu.ActivateGameMenu("village_raid_ended_leaded_by_someone_else");
    }

    public static void GetBattleRewards(
      out float renownChange,
      out float influenceChange,
      out float moraleChange,
      out float goldChange,
      out float playerEarnedLootPercentage,
      ref ExplainedNumber renownExplainedNumber,
      ref ExplainedNumber influenceExplainedNumber,
      ref ExplainedNumber moraleExplainedNumber)
    {
      if (PlayerEncounter.Current == null)
      {
        renownChange = 0.0f;
        influenceChange = 0.0f;
        moraleChange = 0.0f;
        goldChange = 0.0f;
        playerEarnedLootPercentage = 0.0f;
      }
      else
        PlayerEncounter.Current.GetBattleRewardsInternal(out renownChange, out influenceChange, out moraleChange, out goldChange, out playerEarnedLootPercentage, ref renownExplainedNumber, ref influenceExplainedNumber, ref moraleExplainedNumber);
    }

    private void GetBattleRewardsInternal(
      out float renownChange,
      out float influenceChange,
      out float moraleChange,
      out float goldChange,
      out float playerEarnedLootPercentage,
      ref ExplainedNumber renownExplainedNumber,
      ref ExplainedNumber influenceExplainedNumber,
      ref ExplainedNumber moraleExplainedNumber)
    {
      MapEventResultExplainer resultExplainers = this._mapEvent.BattleResultExplainers;
      this._mapEvent.GetBattleRewards(PartyBase.MainParty, out renownChange, out influenceChange, out moraleChange, out goldChange, out playerEarnedLootPercentage);
      if (resultExplainers == null)
        return;
      renownExplainedNumber = resultExplainers.RenownExplainedNumber;
      influenceExplainedNumber = resultExplainers.InfluenceExplainedNumber;
      moraleExplainedNumber = resultExplainers.MoraleExplainedNumber;
    }

    public float GetPlayerStrengthRatioInEncounter()
    {
      List<MobileParty> partiesToJoinPlayerSide = new List<MobileParty>()
      {
        MobileParty.MainParty
      };
      List<MobileParty> partiesToJoinEnemySide = new List<MobileParty>()
      {
        MobileParty.ConversationParty
      };
      this.FindAllNpcPartiesWhoWillJoinEvent(ref partiesToJoinPlayerSide, ref partiesToJoinEnemySide);
      float num1 = 0.0f;
      float num2 = 0.0f;
      foreach (MobileParty mobileParty in partiesToJoinPlayerSide)
      {
        if (mobileParty != null)
          num1 += mobileParty.Party.TotalStrength;
        else
          Debug.FailedAssert("Player side party null", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (GetPlayerStrengthRatioInEncounter), 2338);
      }
      foreach (MobileParty mobileParty in partiesToJoinEnemySide)
      {
        if (mobileParty != null)
          num2 += mobileParty.Party.TotalStrength;
        else
          Debug.FailedAssert("Opponent side party null", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Encounters\\PlayerEncounter.cs", nameof (GetPlayerStrengthRatioInEncounter), 2350);
      }
      if ((double) num2 <= 0.0)
        num2 = 1E-05f;
      return num1 / num2;
    }
  }
}
